"""
项目管理系统的Program模型Services层
"""
from datetime import datetime
from app.Dao.ProgramDao.ProgramDao import ProgramDAO


class ProgramService:
    @staticmethod
    def create_program(user_id, program_name, program_desc, program_status, 
                      goal_id=None, attachment=None):
        """
        创建新项目（包含业务逻辑验证）
        :param user_id: 用户ID
        :param program_name: 项目名称
        :param program_desc: 项目描述
        :param program_status: 项目状态
        :param goal_id: 目标ID（可选）
        :param attachment: 附件路径（可选）
        :return: (bool, 消息, 项目数据)
        """
        # 业务逻辑验证
        if not user_id:
            return False, "用户ID不能为空", None
        
        if not program_name:
            return False, "项目名称不能为空", None
        
        
        # 调用DAO层创建项目
        success, result = ProgramDAO.create_program(
            user_id=user_id,
            program_name=program_name,
            program_desc=program_desc,
            program_status=program_status,
            goal_id=goal_id,
            attachment=attachment
        )
        
        if success:
            return True, "项目创建成功", result
        else:
            if "unique constraint" in result.lower() or "重复" in result:
                return False, "项目名称已存在", None
            return False, f"创建项目失败: {result}", None

    @staticmethod
    def get_program_by_id(program_id):
        """
        通过ID获取项目
        :param program_id: 项目ID
        :return: (bool, 消息, 项目数据)
        """
        if not program_id:
            return False, "项目ID不能为空", None
        
        success, result = ProgramDAO.get_program_by_id(program_id)
        
        if success:
            return True, "获取项目成功", result
        else:
            return False, f"获取项目失败: {result}", None

    @staticmethod
    def get_programs_by_user(user_id, page=1, per_page=10):
        """
        获取用户的所有项目（分页）
        :param user_id: 用户ID
        :param page: 页码
        :param per_page: 每页数量
        :return: (bool, 消息, 分页数据)
        """
        if not user_id:
            return False, "用户ID不能为空", None
        
        if page < 1:
            page = 1
        
        success, result = ProgramDAO.get_programs_by_user(user_id, page, per_page)
        
        if success:
            return True, "获取用户项目列表成功", result
        else:
            return False, f"获取用户项目列表失败: {result}", None

    @staticmethod
    def get_all_programs(page=1, per_page=10):
        """
        获取所有项目（分页）
        :param page: 页码
        :param per_page: 每页数量
        :return: (bool, 消息, 分页数据)
        """
        if page < 1:
            page = 1
        if per_page < 1 or per_page > 100:
            per_page = 10
        
        success, result = ProgramDAO.get_all_programs(page, per_page)
        
        if success:
            return True, "获取所有项目列表成功", result
        else:
            return False, f"获取所有项目列表失败: {result}", None

    @staticmethod
    def update_program(program_id, **kwargs):
        """
        更新项目信息（包含业务逻辑验证）
        :param program_id: 项目ID
        :param kwargs: 要更新的字段
        :return: (bool, 消息, 更新后的项目数据)
        """
        if not program_id:
            return False, "项目ID不能为空", None
        
        
        # 调用DAO层更新项目
        success, result = ProgramDAO.update_program(program_id, **kwargs)
        
        if success:
            return True, "项目更新成功", result
        else:
            if "unique constraint" in result.lower() or "重复" in result:
                return False, "项目名称已存在", None
            if "项目不存在" in result:
                return False, result, None
            return False, f"更新项目失败: {result}", None

    @staticmethod
    def delete_program(program_id):
        """
        删除项目（包含业务逻辑验证）
        :param program_id: 项目ID
        :return: (bool, 消息, None)
        """
        if not program_id:
            return False, "项目ID不能为空", None
        
        # 可以在这里添加删除前的业务检查，比如项目是否有关联数据等
        # 示例：检查项目是否有子任务（如果有相关联的表）
        # success_check, result_check = TaskDAO.get_tasks_by_program(program_id)
        # if success_check and result_check.items:
        #     return False, "该项目下存在子任务，无法删除", None
        
        success, result = ProgramDAO.delete_program(program_id)
        
        if success:
            return True, result, None
        else:
            return False, f"删除项目失败: {result}", None

    @staticmethod
    def get_programs_by_status(program_status, page=1, per_page=10):
        """
        根据状态获取项目
        :param program_status: 项目状态
        :param page: 页码
        :param per_page: 每页数量
        :return: (bool, 消息, 分页数据)
        """
        if program_status is None:
            return False, "项目状态不能为空", None
        
        if page < 1:
            page = 1
        if per_page < 1 or per_page > 100:
            per_page = 10
        
        success, result = ProgramDAO.get_programs_by_status(program_status, page, per_page)
        
        if success:
            return True, "获取指定状态项目列表成功", result
        else:
            return False, f"获取指定状态项目列表失败: {result}", None

    @staticmethod
    def get_programs_by_goal(goal_id, page=1, per_page=10):
        """
        根据目标ID获取项目
        :param goal_id: 目标ID
        :param page: 页码
        :param per_page: 每页数量
        :return: (bool, 消息, 分页数据)
        """
        if not goal_id:
            return False, "目标ID不能为空", None
        
        if page < 1:
            page = 1
        if per_page < 1 or per_page > 100:
            per_page = 10
        
        success, result = ProgramDAO.get_programs_by_goal(goal_id, page, per_page)
        
        if success:
            return True, "获取指定目标项目列表成功", result
        else:
            return False, f"获取指定目标项目列表失败: {result}", None

    @staticmethod
    def search_programs(keyword, page=1, per_page=10):
        """
        搜索项目（按名称或描述）
        :param keyword: 搜索关键词
        :param page: 页码
        :param per_page: 每页数量
        :return: (bool, 消息, 分页数据)
        """
        if not keyword or len(keyword) < 1:
            return False, "搜索关键词不能为空", None
        
        if page < 1:
            page = 1
        if per_page < 1 or per_page > 100:
            per_page = 10
        
        success, result = ProgramDAO.search_programs(keyword, page, per_page)
        
        if success:
            return True, "搜索项目成功", result
        else:
            return False, f"搜索项目失败: {result}", None

    @staticmethod
    def batch_delete_programs(program_ids):
        """
        批量删除项目
        :param program_ids: 项目ID列表
        :return: (bool, 消息, 删除成功的数量)
        """
        if not program_ids or not isinstance(program_ids, list):
            return False, "项目ID列表不能为空且必须为列表", None
        
        success_count = 0
        failed_ids = []
        
        for program_id in program_ids:
            success, result = ProgramDAO.delete_program(program_id)
            if success:
                success_count += 1
            else:
                failed_ids.append(program_id)
        
        if success_count > 0:
            message = f"成功删除{success_count}个项目"
            if failed_ids:
                message += f"，失败ID: {failed_ids}"
            return True, message, success_count
        else:
            return False, f"批量删除失败，失败ID: {failed_ids}", 0

    @staticmethod
    def get_program_statistics(user_id=None):
        """
        获取项目统计信息
        :param user_id: 用户ID（可选，为空则获取所有）
        :return: (bool, 消息, 统计数据)
        """
        try:
            # 获取状态统计
            if user_id:
                all_programs = ProgramDAO.get_programs_by_user(user_id, page=1, per_page=1000)[1]
            else:
                all_programs = ProgramDAO.get_all_programs(page=1, per_page=1000)[1]
            
            stats = {
                'total': all_programs.total,
                'by_status': {},
                'recently_updated': []
            }
            
            # 按状态统计
            for program in all_programs.items:
                status = program.program_status
                if status not in stats['by_status']:
                    stats['by_status'][status] = 0
                stats['by_status'][status] += 1
            
            # 获取最近更新的项目
            recent_programs = sorted(
                all_programs.items,
                key=lambda x: x.update_time,
                reverse=True
            )[:5]
            stats['recently_updated'] = recent_programs
            
            return True, "获取项目统计信息成功", stats
        except Exception as e:
            return False, f"获取项目统计信息失败: {str(e)}", None